package com.menghao.sso.server.service;

import com.menghao.sso.server.exception.InvalidTicketException;
import com.menghao.sso.server.exception.ValidateFailException;
import com.menghao.sso.server.model.Principal;
import com.menghao.sso.server.model.Service;
import com.menghao.sso.server.model.SimplePrincipal;
import com.menghao.sso.server.model.credentials.Credentials;
import com.menghao.sso.server.model.credentials.UsernamePasswordCredentials;
import com.menghao.sso.server.model.ticket.ServiceTicket;
import com.menghao.sso.server.model.ticket.TicketGrantingTicket;
import com.menghao.sso.server.model.ticket.TicketGrantingTicketImpl;
import com.menghao.sso.server.model.validation.Authentication;
import com.menghao.sso.server.registry.ExpirationPolicy;
import com.menghao.sso.server.registry.TicketRegistry;
import com.menghao.sso.server.util.TicketIdGenerator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.util.HashMap;

/**
 * <p>授权Service实现.<br>
 *
 * @author menghao.
 * @version 2017/11/17.
 */
@org.springframework.stereotype.Service
public class AuthorizationServiceImpl implements AuthorizationService {

    private final Log log = LogFactory.getLog(this.getClass());

    @Autowired
    private TicketRegistry ticketRegistry;
    @Autowired
    private ExpirationPolicy expirationPolicy;

    @Override
    public String createTicketGrantingTicket(Credentials credentials) throws ValidateFailException {
        if (credentials instanceof UsernamePasswordCredentials) {
            String username = ((UsernamePasswordCredentials) credentials).getUsername();
            if (!StringUtils.hasText(username)) {
                throw new ValidateFailException("无法获取用户名");
            }
            String tgtId = TicketIdGenerator.newTGTId();
            Principal principal = new SimplePrincipal(username);
            Authentication authentication = new Authentication(principal, new HashMap());
            ticketRegistry.addTicket(new TicketGrantingTicketImpl(tgtId, authentication, this.expirationPolicy));
            return tgtId;
        }
        return null;
    }

    @Override
    public String createServiceTicket(String ticketGrantingTicketId, Service service) throws ValidateFailException {
        if (!StringUtils.hasText(ticketGrantingTicketId)) {
            throw new ValidateFailException("未检测到票据信息，请登录");
        }
        TicketGrantingTicket ticketGrantingTicket = (TicketGrantingTicket) ticketRegistry.getTicket(ticketGrantingTicketId);

        if (ticketGrantingTicket == null) {
            throw new ValidateFailException("票据信息校验未通过，请登录");
        }

        if (ticketGrantingTicket.isExpired()) {
            throw new ValidateFailException("身份验证已过期，请重新登录");
        }

        final ServiceTicket serviceTicket = ticketGrantingTicket.grantServiceTicket(
                TicketIdGenerator.newSTId(), service, this.expirationPolicy);

        this.ticketRegistry.addTicket(serviceTicket);

        log.info("Granted service ticket ["
                + serviceTicket.getId()
                + "] for service ["
                + service.getUrl()
                + "] for user ["
                + serviceTicket.getGrantingTicket().getAuthentication()
                .getPrincipal().getUrl() + "]");

        return serviceTicket.getId();
    }

    @Override
    public void destroyTicketGrantingTicket(String ticketGrantingTicketId) throws InvalidTicketException {
        if (!StringUtils.hasText(ticketGrantingTicketId)) {
            throw new InvalidTicketException();
        }
        ticketRegistry.deleteTicket(ticketGrantingTicketId);
    }
}
